# weather.py
# 导入必要的库
import requests  # 用于发送HTTP请求
from bs4 import BeautifulSoup  # 用于解析HTML内容
import csv  # 用于读写CSV文件
import json  # 用于解析JSON数据
import os  # 用于与操作系统进行交互


def getHTMLtext(url):
    """请求获得网页内容"""
    try:
        # 发送GET请求到指定URL，并设置超时时间为30秒
        r = requests.get(url, timeout=30)
        # 检查请求是否成功（状态码200表示成功）
        r.raise_for_status()
        # 打印出响应内容的UTF-8解码文本
        print(r.content.decode("utf-8"))
        # 设置正确的编码以防止中文乱码
        r.encoding = r.apparent_encoding
        print("成功访问")
        return r.text  # 返回响应的文本内容
    except Exception as e:  # 捕获所有异常
        print(f"访问错误: {e}")  # 打印具体的错误信息
        return " "  # 如果发生错误，返回一个空字符串


def get_content(html):
    """处理得到有用信息保存数据文件"""
    final = []  # 初始化列表存储最终结果
    bs = BeautifulSoup(html, "html.parser")  # 使用BeautifulSoup解析HTML
    body = bs.body  # 获取HTML的body部分
    data = body.find('div', {'id': '7d'})  # 查找id为'7d'的div元素，该元素包含7天天气预报
    # 爬取当天的数据
    data2 = body.find_all('div', {'class': 'left-div'})  # 查找所有class为'left-div'的div元素
    text = data2[2].find('script').string  # 在第三个匹配项中查找<script>标签内的文本
    text = text[text.index('=') + 1:-2]  # 去除javascript变量声明，保留JSON格式的数据
    jd = json.loads(text)  # 将字符串转换为Python对象
    dayone = jd['od']['od2']  # 获取当天每小时的数据
    final_day = []  # 存储当天的数据
    count = 0  # 计数器
    for i in dayone:  # 遍历当天每小时的数据
        temp = []
        if count <= 23:
            temp.append(i['od21'])  # 添加时间
            temp.append(i['od22'])  # 添加当前时刻温度
            temp.append(i['od24'])  # 添加当前时刻风力方向
            temp.append(i['od25'])  # 添加当前时刻风级
            temp.append(i['od26'])  # 添加当前时刻降水量
            temp.append(i['od27'])  # 添加当前时刻相对湿度
            temp.append(i['od28'])  # 添加当前时刻控制质量
            # print(temp)
            final_day.append(temp)  # 将每小时的数据添加到final_day列表中
        count += 1
    # 下面爬取7天的数据
    ul = data.find('ul')  # 查找ul元素，它包含了接下来几天的天气信息
    li = ul.find_all('li')  # 查找所有的li元素，每个代表一天
    i = 0  # 控制爬取的天数
    for day in li:  # 遍历找到的每一个li
        if 7 > i > 0:  # 忽略第一个和超过7天的数据
            temp = []  # 临时存放每天的数据
            date = day.find('h1').string  # 得到日期
            date = date[0:date.index('日')]  # 取出日期号
            temp.append(date)
            inf = day.find_all('p')  # 找出li下面的p标签,提取第一个p标签的值，即天气
            temp.append(inf[0].string)

            tem_low = inf[1].find('i').string  # 找到最低气温

            if inf[1].find('span') is None:  # 天气预报可能没有最高气温
                tem_high = None
            else:
                tem_high = inf[1].find('span').string  # 找到最高气温
            temp.append(tem_low[:-1])
            if tem_high[-1] == '℃':
                temp.append(tem_high[:-1])
            else:
                temp.append(tem_high)

            wind = inf[2].find_all('span')  # 找到风向
            for j in wind:
                temp.append(j['title'])

            wind_scale = inf[2].find('i').string  # 找到风级
            index1 = wind_scale.index('级')
            temp.append(int(wind_scale[index1 - 1:index1]))
            final.append(temp)  # 将每天的数据添加到final列表中
        i += 1
    return final_day, final  # 返回当天和接下来7天的数据
    # print(final)


def get_content2(html):
    """处理得到有用信息保存数据文件"""
    final = []  # 初始化一个列表保存数据
    bs = BeautifulSoup(html, "html.parser")  # 创建BeautifulSoup对象
    body = bs.body
    data = body.find('div', {'id': '15d'})  # 找到div标签且id = 15d
    ul = data.find('ul')  # 找到所有的ul标签
    li = ul.find_all('li')  # 找到左右的li标签
    i = 0  # 控制爬取的天数
    for day in li:  # 遍历找到的每一个li
        if i < 8:
            temp = []  # 临时存放每天的数据
            date = day.find('span', {'class': 'time'}).string  # 得到日期
            date = date[date.index('（') + 1:-2]  # 取出日期号
            temp.append(date)
            weather = day.find('span', {'class': 'wea'}).string  # 找到天气
            temp.append(weather)
            tem = day.find('span', {'class': 'tem'}).text  # 找到温度
            temp.append(tem[tem.index('/') + 1:-1])  # 找到最低气温
            temp.append(tem[:tem.index('/') - 1])  # 找到最高气温
            wind = day.find('span', {'class': 'wind'}).string  # 找到风向
            if '转' in wind:  # 如果有风向变化
                temp.append(wind[:wind.index('转')])
                temp.append(wind[wind.index('转') + 1:])
            else:  # 如果没有风向变化，前后风向一致
                temp.append(wind)
                temp.append(wind)
            wind_scale = day.find('span', {'class': 'wind1'}).string  # 找到风级
            index1 = wind_scale.index('级')
            temp.append(int(wind_scale[index1 - 1:index1]))

            final.append(temp)
    return final


def write_to_csv(file_name, data, day=14):
    """保存为csv文件"""
    with open(file_name, 'a', errors='ignore', newline='') as f:
        if day == 14:
            header = ['日期', '天气', '最低气温', '最高气温', '风向1', '风向2', '风级']
        else:
            header = ['小时', '温度', '风力方向', '风级', '降水量', '相对湿度', '空气质量']
        f_csv = csv.writer(f)  # 创建CSV写入对象
        f_csv.writerow(header)  # 写入表头
        f_csv.writerows(data)  # 写入数据行


def main():
    """主函数"""
    print("Weather test")
    # 定义上海的7天和15天天气预报URL
    url1 = 'http://www.weather.com.cn/weather/101020100.shtml'
    url2 = 'http://www.weather.com.cn/weather15d/101020100.shtml'

    html1 = getHTMLtext(url1)  # 获取7天天气预报的HTML
    data1, data1_7 = get_content(html1)  # 获取当天和接下来7天的天气数据

    html2 = getHTMLtext(url2)  # 获取15天天气预报的HTML
    data8_14 = get_content2(html2)  # 获取第8到14天的天气数据
    data14 = data1_7 + data8_14  # 合并7天和8-14天的数据

    file_path1 = 'weather14.csv'  # 定义14天天气预报的CSV文件路径
    file_path2 = 'weather1.csv'  # 定义当天天气预报的CSV文件路径

    # 检查并删除已存在的CSV文件
    for file_path in [file_path1, file_path2]:
        if os.path.exists(file_path):
            os.remove(file_path)
            print(f'文件 {file_path} 已删除。')
        else:
            print(f'文件 {file_path} 不存在。')

    # 将天气数据写入CSV文件
    write_to_csv(file_path1, data14, 14)  # 写入14天的数据
    print(f'成功创建文件 {file_path1}')
    write_to_csv(file_path2, data1, 1)  # 写入当天的数据
    print(f'成功创建文件 {file_path2}')


if __name__ == '__main__':
    main() # 当脚本被直接运行时，调用main函数
